/*
 * bluetork
 */

// 模式名称
const modeName = [
  '', //SN
  'MN',
  'MA',
  '', //SA
]
// 模式命令 寄存器地址+寄存器个数+数据长度
const modeCmd = {
  reg: [
    [], // SN模式 ['06', '70']
    ['06', 'AC'], // MN模式
    ['06', 'D4'], // MA模式
    [], // SA模式 ['06', '81']
  ],
  regNum: [
    [], // SN模式 ['00', '02']
    ['00', '04'], // MN模式
    ['00', '06'], // MA模式
    [], // SA模式 ['00', '04']
  ],
  len: [
    '', // SN模式 '04'
    '08', // MN模式
    '0C', //MA模式
    '', //SA模式 '08'
  ],
}
function getUnitCmd(tork_unit) {
  // 00：Nm 01：inlb 02：ftlb 03：kgcm 04：kgm
  let unitMpa = ['nm', 'inlb', 'ftlb', 'kgcm', 'kgm'].map((v) => v.toLowerCase())
  const reg = ['06', '40']
  const unit = unitMpa.indexOf(tork_unit.toLowerCase()).toString(16).padStart(2, '0')
  const cmd = ['01', '06', ...reg, '00', unit]
  return cmd
}
/**
 * 设置相关的命令
 * @param {'close'|'clear'} type 命令类型
 * @returns {String[]} 指令数组
 */
function setCmd(type) {
  switch (type) {
    case 'close':
      return ['01', '06', '00', '02', '00', '00'] //关机
    case 'clear':
      return ['01', '06', '00', '01', '00', '00'] //清零
    case 'heartbeat':
      // return ['01', '10', '06', '49', '00', '03', '06', '00', '00', '00', '20', '00', '6E'] //设置心跳 关闭心跳格式，帧数32 间隔110ms
      return ['01', '10', '06', '49', '00', '03', '06', '00', '00', '00', '22', '00', '6E'] //设置心跳 关闭心跳格式，帧数32 间隔110ms
    default:
      return []
    // throw new Error('未知的设置类型')
  }
}
/**
 * 读取相关的命令
 * @param {'critical'} type 命令类型
 * @returns {String[]} 指令数组
 */
function getCmd(type) {
  switch (type) {
    case 'critical':
      return ['01', '03', '05', '20', '00', '16'] //读取临界参数
    case 'heartbeat':
      return ['01', '06', '00', '08', '00', '01'] //触发心跳
    default:
      return []
    // throw new Error('未知的读取类型')
  }
}

/**
 * 获取初始化读取命令 √
 * @returns {String[]} 初始化读取命令
 */
// function getInitReadCmd() {
//   return getCmd('critical')
// }

/**
 * 获取设置模式命令 √
 * @param {Object} order 工单
 * @param {String} order.worktype 工单类型
 * @returns {String[]} 设置模式的指令
 */
function setModeCmd(order) {
  console.log('order', order)
  const { worktype /*,  tork_unit */ } = order
  // let unitMpa = ['nm', 'ftlb', 'inlb', 'kgfcm'].map((v) => v.toLowerCase())

  const Ax = {
    EN: ['00', '00'],
    EA: ['00', '01'],
    SN: ['00', '02'],
    SA: ['00', '03'],
    MN: ['00', '04'],
    MA: ['00', '05'],
  }
  // A1,A2模式 00 = A1模式(扭矩模式) 01 = A2模式(角度模式)
  const pos = worktype.match(/\d/g) // pos[0] == 1 A1  pos[1] == 0 M0
  const mode = modeName[pos[0]] // 模式名称
  const modeA = Ax[mode] // 模式A值

  // P/T模式 00 = T模式(追随模式); 01 = P模式(峰值模式)
  // let pt = '01'

  // 扭矩单位 00 = N·m; 01 = lbf·in; 02 = lbf·ft; 03 = kgf·cm
  // let unit = unitMpa.indexOf(tork_unit.toLowerCase()).toString(16).padStart(2, '0')

  // M0 - M9 => 00,01,02,03,04,05,06,07,08,09
  const modeM = HexCalculator.formatHexArray(pos[1], 2)

  // 角度挡位 0 = 15°/s,4 = 250°/s, 1 = 30°/s, 5 = 500°/s, 2 = 60°/s, 6 = 1000°/s, 3 = 120°/s,7 = 2000°/s
  // let angle = '00'

  let cmd = ['01', '10', '06', '44', '00', '02', '04']
  cmd.push(...modeA, ...modeM)
  console.log('设置模式:', cmd.join(' '))
  return cmd
}
/**
 * 写入模式命令 --Sx、Mx起始寄存器地址
 * @param {String} type - 模式类型字符串，如 'A1M1'
 * @returns obj 返回包含模式配置的对象
 * @returns {string} obj.mode - 模式名称 (如 'MN')
 * @returns {string[]} obj.reg - 寄存器地址数组
 * @returns {string[]} obj.regNum - 寄存器个数
 * @returns {string} obj.len - 数据长度
 * @example writeModeCmd('A1M1')
 */
// function writeModeCmd(type) {
//   const pos = type.match(/\d/g) // pos[0] == 1 A1  pos[1] == 0 M0

//   const regNum = modeCmd.regNum[pos[0]] // 寄存器个数
//   const regAdd = HexCalculator.multiply(regNum, pos[1], false)
//   const reg = HexCalculator.add(modeCmd.reg[pos[0]], regAdd) //寄存器地址
//   const len = modeCmd.len[pos[0]] // 数据长度
//   return {
//     mode: modeName[pos[0]],
//     reg,
//     regNum,
//     len,
//     cmd: ['01', '10', ...reg, ...regNum, len],
//   }
// }

/**
 * 获取发送数据的buffer --单条发送 √
 * @param {*} sendData
 * @returns
 */
// function getSendDataCmd(sendData) {
//   console.log('senddata', sendData)
//   // let {worktype_name, target_tork, max_tork, min_tork, angle, max_angle, min_angle} = sendData;
//   let { worktype, target_tork, max_tork, min_tork, angle, max_angle, min_angle } = sendData
//   // 模式 A1 是扭矩模式；A2 是角度模
//   const pos = worktype.match(/\d/g) // pos[0] == 1 A1  pos[1] == 0 M0
//   const mode = modeName[pos[0]]
//   const regNum = modeCmd.regNum[pos[0]] // 寄存器个数
//   const regAdd = HexCalculator.multiply(regNum, pos[1], false)
//   const reg = HexCalculator.add(modeCmd.reg[pos[0]], regAdd) //寄存器地址
//   const len = modeCmd.len[pos[0]] // 数据长度
//   let cmd = ['01', '10', ...reg, ...regNum, len]

//   // 数据段
//   switch (mode) {
//     case 'SN':
//       cmd.push(...HexCalculator.formatHexArray(target_tork * 1000, 4))
//       // console.log('目标扭矩：',);
//       break
//     case 'SA':
//       cmd.push(...HexCalculator.formatHexArray(target_tork * 1000, 4))
//       cmd.push(...HexCalculator.formatHexArray(angle * 1000, 4))
//       // console.log('目标角度：', angle, angleArr);
//       break
//     case 'MN':
//       cmd.push(...HexCalculator.formatHexArray(min_tork * 1000, 4))
//       // console.log('扭矩下限：', min_tork, torqueMinArr);
//       cmd.push(...HexCalculator.formatHexArray(max_tork * 1000, 4))
//       // console.log('扭矩上限：', max_tork, torqueMaxArr);
//       break
//     case 'MA':
//       cmd.push(...HexCalculator.formatHexArray(target_tork * 1000, 4))
//       cmd.push(...HexCalculator.formatHexArray(min_angle * 1000, 4))
//       // console.log('角度下限', min_angle, angleMinArr);
//       cmd.push(...HexCalculator.formatHexArray(max_angle * 1000, 4))
//       // console.log('角度上限', max_angle, angleMaxArr);
//       break
//     default:
//       throw new Error('模式错误')
//   }

//   console.log('发送命令:', cmd.join(' '))
//   return cmd
// }

/**
 * 获取发送数据的指令 --批量发送 √
 * @param {Object[]} orders 工单列表
 * @param {String} orders[].worktype 工单类型
 * @param {Number} orders[].target_tork 目标扭矩值
 * @param {Number} orders[].max_tork 最大扭矩值
 * @param {Number} orders[].min_tork 最小扭矩值
 * @param {Number} orders[].angle 目标角度值
 * @param {Number} orders[].max_angle 最大角度值
 * @param {Number} orders[].min_angle 最小角度值
 * @returns {String[][]} 工单数据的指令
 */
function getSendOrderBatchCmd(orders) {
  console.log('orders', orders)

  // let { worktype, target_tork, max_tork, min_tork, angle, max_angle, min_angle } = orders[0]
  // 模式 A1 是扭矩模式；A2 是角度模
  const pos = orders[0].worktype.match(/\d/g) // pos[0] == 1 A1  pos[1] == 0 M0
  console.log('pos', pos)
  const mode = modeName[pos[0]] // 模式名称
  console.log('模式名称:', mode)
  const reg = modeCmd.reg[pos[0]] //寄存器地址
  const regNum = HexCalculator.multiply(modeCmd.regNum[pos[0]], 'a') // 寄存器个数 2位 数组
  const len = parseInt(modeCmd.len[pos[0]], 16) // 1个数据长度
  const totalLen = HexCalculator.multiply(len, 'a', false) // 总数据长度 1位 字符串
  let cmd = ['01', '10', ...reg, ...regNum, totalLen]

  // 数据段
  let data = Array(parseInt(totalLen, 16)).fill('00')
  // 参数
  let args = []
  switch (mode) {
    case 'SN':
      args = ['target_tork']
      break
    case 'SA':
      args = ['target_tork', 'angle']
      break
    case 'MN':
      args = ['min_tork', 'max_tork']
      break
    case 'MA':
      args = ['target_tork', 'min_angle', 'max_angle']
      break
    default:
      throw new Error('模式错误')
  }
  for (const order of orders) {
    let index = order.worktype.match(/\d/g)[1] * len
    for (let i = 0; i < args.length; i++) {
      const value = HexCalculator.formatHexArray(order[args[i]] * 1000, 4)
      data.splice(index + 4 * i, 4, ...value)
    }
    // let i = 1
    // for (const arg of args) {
    //   const value = HexCalculator.formatHexArray(order[arg] * 1000, 4)
    //   data.splice(index + 4 * i, 4, ...value)
    //   i++
    // }
  }
  // console.log('发送命令:', [...cmd, ...resData])
  return [[...cmd, ...data]]
}

/**
 * 解析设备报警参数 临界值 √
 * @param {String[]} data 数据值
 * @returns {{
 * min_tork:number,
 * max_tork:number
 * }} object 最小可调报警值 最大可调报警值
 */
function readDeviceCriticalValue(data) {
  console.log('readDeviceCriticalValue-data', data)

  const len = data[2].toLocaleLowerCase()
  if (len != '2c') throw new Error('数据错误')

  const min_tork = HexCalculator.formatToNumber(data.slice(31, 35).join(''))
  const max_tork = HexCalculator.formatToNumber(data.slice(35, 39).join(''))

  console.log('min_tork:', min_tork)
  console.log('max_tork:', max_tork)
  return {
    min_tork,
    max_tork,
  }
}

/**
 * 解析心跳数据 √
 * @param {String[]} arr 心跳数据
 * @returns obj 设备数据
 * @returns {string} obj.datetime_work 设备数据
 * @returns {string} obj.datetime_work1 设备数据
 * @returns {number} obj.tork 设备数据
 * @returns {number} obj.max_tork 设备数据
 * @returns {number} obj.angle 设备数据
 */
function formatDeviceData(arr) {
  if (arr.length < 9) return
  let d = new Date()
  let datetime = d.toJSON().substring(0, 19).replace('T', ' ')
  let datetime1 =
    [
      d.getFullYear(),
      (d.getMonth() + 1).toString().padStart(2, '0'),
      d.getDate().toString().padStart(2, '0'),
    ].join('-') +
    ' ' +
    [
      d.getHours().toString().padStart(2, '0'),
      d.getMinutes().toString().padStart(2, '0'),
      d.getSeconds().toString().padStart(2, '0'),
    ].join(':')

  const tork = HexCalculator.formatToNumber(arr.slice(3, 7))
  const max_tork = HexCalculator.formatToNumber(arr.slice(7, 11))

  const angle = HexCalculator.formatToNumber(arr.slice(11, 15))
  const angle_sum = HexCalculator.formatToNumber(arr.slice(15, 19))

  // let unit = (['0x', arr[14]].join('') >> 2) & 0x03

  // res.unit = ['Nm', 'lbfin', 'lbfft', 'kgfcm'][unit] || 'ERROR'
  let res = {
    // 工作时间
    datetime_work: datetime,
    datetime_work1: datetime1,
    // 扭矩 设备返回来的数据
    tork,
    max_tork,
    // 角度 设备返回来的数据
    angle,
    angle_sum,
    // 扳手设备ID TODO:
    // wrench_identity: '',
    // 单位
    // unit: '',
  }
  // console.log('formatDeviceData', JSON.stringify(res))

  return res
}

/**
 * 在数组前面填充指定数量的指定元素
 * @param {string[]} array - 原始数组
 * @param {number} length - 需要填充到的长度
 * @param {string} fillValue - 填充值，默认为'00'
 * @returns {string[]} 填充后的数组
 */
// function padStartArray(array, length, fillValue = '00') {
//   const fillCount = length - array.length
//   if (fillCount < 0) {
//     throw new Error('数组长度已经大于指定长度')
//     // return array
//   }
//   // 创建填充数组
//   const padding = Array(fillCount).fill(fillValue)
//   // 合并填充数组和原数组
//   return [...padding, ...array]
// }
/**
 * 十六进制计算器工具 - 支持字符串或数组参数，返回16进制结果 -字符串
 */
const HexCalculator = {
  /**
   * 解析输入参数为十进制数值
   * @param {string|string[]} input - 输入参数
   * @returns {number} 十进制数值
   */
  parseInput: function (input) {
    if (Array.isArray(input)) {
      // 如果是数组，合并为完整十六进制字符串
      return parseInt(input.join(''), 16)
    } else {
      // 如果是字符串，直接解析
      return parseInt(input, 16)
    }
  },
  /**
   * 格式化数值为十进制
   * @param {String|String[]} hex 十六进制值或数组
   * @returns 返回十进制数值
   */
  formatToNumber(hex) {
    Array.isArray(hex) && (hex = hex.join(''))
    return Number((parseInt(hex, 16) / 1000).toFixed(3))
  },
  /**
   * 格式化十六进制值为2位字符串的数组
   * @param {string|number} hex - string:十六进制值 | number:十进制值
   * @param {Boolean|Number} length - 指定数组长度 false: 不指定长度 | number: 指定长度
   * @returns {string[]} 2位字符串的数组
   */
  formatHexArray: function (hex, length = false) {
    let hexStr = typeof hex === 'number' ? hex.toString(16) : hex
    hexStr = hexStr.length % 2 ? '0' + hexStr : hexStr
    const arr = hexStr.split(/(.{2})/g).filter((v) => v)
    return length ? this.padStartArray(arr, length) : arr
  },
  /**
   * 在数组前面填充指定数量的指定元素
   * @param {string[]} array - 原始数组
   * @param {number} length - 需要填充到的长度
   * @param {string} fillValue - 填充值，默认为'00'
   * @returns {string[]} 填充后的数组
   */
  padStartArray: function (array, length, fillValue = '00') {
    const fillCount = length - array.length
    if (!fillCount && fillCount < 0) {
      throw new Error('数组长度已经大于指定长度')
      // return array
    }
    // 创建填充数组
    const padding = Array(fillCount).fill(fillValue)
    // 合并填充数组和原数组
    return [...padding, ...array]
  },
  /**
   * 在数组后面填充指定数量的指定元素
   * @param {string[]} array - 原始数组
   * @param {number} length - 需要填充到的长度
   * @param {string} fillValue - 填充值，默认为'00'
   * @returns {string[]} 填充后的数组
   */
  padEndArray: function (array, length, fillValue = '00') {
    const fillCount = length - array.length
    if (fillCount < 0) {
      throw new Error('数组长度已经大于指定长度')
      // return array
    }
    // 创建填充数组
    const padding = Array(fillCount).fill(fillValue)
    // 合并填充数组和原数组
    return [...array, ...padding]
  },

  /**
   * 加法运算
   * @param {string|string[]} h1 - 第一个十六进制值
   * @param {string|string[]} h2 - 第二个十六进制值
   * @param {Boolean|Number} format - 是否格式化 默认值2 false不格式化 true格式化为2位字符串的数组 number指定长度的数组
   * @returns {string|string[]} 十六进制字符串 或 2位字符串的 指定长度数组
   */
  add: function (h1, h2, format = 2) {
    const val1 = this.parseInput(h1)
    const val2 = this.parseInput(h2)
    const result = val1 + val2
    if (format) {
      const res = this.formatHexArray(result.toString(16))
      if (format == true) {
        return res
      } else {
        return this.padStartArray(res, format)
      }
    } else {
      return result.toString(16)
    }
  },

  /**
   * 减法运算
   * @param {string|string[]} h1 - 第一个十六进制值
   * @param {string|string[]} h2 - 第二个十六进制值
   * @param {Boolean|Number} format - 是否格式化 false不格式化 true格式化为2位字符串的数组 number指定长度的数组
   * @returns {string|string[]} 十六进制字符串 或 2位字符串的 指定长度数组
   */
  subtract: function (h1, h2, format = 2) {
    const val1 = this.parseInput(h1)
    const val2 = this.parseInput(h2)
    const result = val1 - val2
    if (format) {
      const res = this.formatHexArray(result.toString(16))
      if (format == true) {
        return res
      } else {
        return this.padStartArray(res, format)
      }
    } else {
      return result.toString(16)
    }
  },

  /**
   * 乘法运算
   * @param {string|string[]} h1 - 第一个十六进制值
   * @param {string|string[]} h2 - 第二个十六进制值
   * @param {Boolean|Number} format - 是否格式化 false不格式化 true格式化为2位字符串的数组 number指定长度的数组
   * @returns {string|string[]} 十六进制字符串 或 2位字符串的 指定长度数组
   */
  multiply: function (h1, h2, format = 2) {
    const val1 = this.parseInput(h1)
    const val2 = this.parseInput(h2)
    const result = val1 * val2
    if (format) {
      const res = this.formatHexArray(result.toString(16))
      if (format == true) {
        return res
      } else {
        return this.padStartArray(res, format)
      }
    } else {
      return result.toString(16)
    }
  },

  /**
   * 除法运算
   * @param {string|string[]} h1 - 第一个十六进制值
   * @param {string|string[]} h2 - 第二个十六进制值
   * @param {Boolean|Number} format - 是否格式化 false不格式化 true格式化为2位字符串的数组 number指定长度的数组
   * @returns {string|string[]} 十六进制字符串 或 2位字符串的 指定长度数组
   */
  divide: function (h1, h2, format = 2) {
    const val1 = this.parseInput(h1)
    const val2 = this.parseInput(h2)
    const result = Math.floor(val1 / val2) // 整数除法
    if (format) {
      const res = this.formatHexArray(result.toString(16))
      if (format == true) {
        return res
      } else {
        return this.padStartArray(res, format)
      }
    } else {
      return result.toString(16)
    }
  },
}

// function arrayToBuffer(arr) {
//   let cmd = arr.map((v) => '0x' + v)
//   // console.log("arrayToBuffer", cmd)
//   let uint16arr = new Uint8Array(cmd)
//   return uint16arr.buffer //返回由 Uint8Array引用的 ArrayBuffer
// }
// CRC-16/MODBUS 校验
// function crc16modbus(data) {
//   const dataBytes = data.map((v) => parseInt(v, 16))

//   let crc = 0xffff
//   const polynomial = 0xa001 // This is the polynomial x^16 + x^15 + x^2 + 1

//   for (const byte of dataBytes) {
//     crc ^= byte
//     for (let i = 0; i < 8; i++) {
//       if (crc & 0x0001) {
//         crc = ((crc >> 1) ^ polynomial) & 0xffff
//       } else {
//         crc >>= 1
//       }
//     }
//   }

//   return crc.toString(16).toUpperCase().padStart(4, '0').match(/\w{2}/g).reverse()
// }
export default {
  cmd: {
    setCmd,
    getCmd,
    // getInitReadCmd,
    setModeCmd,
    // getSendDataCmd,
    getSendOrderBatchCmd,
    getUnitCmd,
  },
  readDeviceCriticalValue,
  formatDeviceData,
}
